 bondscell_results$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01queued¤logsrunning¦outputbody<div class="markdown"><h1 id="Using-Macros">Using Macros</h1>
<h2 id="Creation">Creation</h2>
<p>Defining a macro is like defining a function. For example,</p>
<pre><code class="language-julia-repl">julia&gt; macro sayhello&#40;name&#41;
    return :&#40; println&#40;&quot;Hello&quot;, &#36;name&#41;&#41;
end
@sayhello &#40;macro with 1 method&#41;</code></pre>
<p>Now invoke the <code>@sayhello</code> macro.</p>
<pre><code class="language-julia-repl">julia&gt; @sayhello&#40;&quot;world&quot;&#41;
Helloworld</code></pre>
<p>Parentheses around the arguments are optional.</p>
<pre><code class="language-julia-repl">julia&gt; @sayhello &quot;world&quot;
Helloworld</code></pre>
<div class="admonition note"><p class="admonition-title">Note</p><p>When using the parenthesized form, there should be no space between the macro name and the parentheses. Otherwise the argument list will be interpreted as a single argument containing a Tuple.</p>
</div>
<h2 id="Usage">Usage</h2>
<p>Macros can be used for many tasks such as performing operations on blocks of code, such as timing expressions &#40;<code>@time</code>&#41;, threading <code>for</code> loops &#40;<code>@threads</code>&#41;, and converting expressions to broadcast form &#40;<code>@.</code>&#41;. Another use is to generate code. When a significant amount of repetitive boilerplate code is required, it is common to generate it programmatically to avoid redundancy.</p>
<p>Consider the following example.</p>
<pre><code class="language-julia-repl">julia&gt; struct MyNumber
    x::Float64
end</code></pre>
<p>We want to add a various methods to it. This can be done programmatically using a <code>for</code> loop.</p>
<pre><code class="language-julia-repl">julia&gt; length&#40;methods&#40;sin&#41;&#41;
14

julia&gt; for op &#61; &#40;:sin, :tan, :log, :exp&#41;
    eval&#40;quote
        Base.&#36;op&#40;a::MyNumber&#41; &#61; MyNumber&#40;&#36;op&#40;a.x&#41;&#41;
	end&#41;
end

julia&gt; length&#40;methods&#40;sin&#41;&#41;
15</code></pre>
<p>A slightly shorter version of the above code generator that use the <code>:</code> prefix is:</p>
<pre><code class="language-julia-repl">julia&gt; for op &#61; &#40;:sin, :cos, :tan, :log, :exp&#41;
    eval&#40;:&#40;Base.&#36;op&#40;a::MyNumber&#41; &#61; MyNumber&#40;&#36;op&#40;a.x&#41;&#41;&#41;&#41;
end</code></pre>
<p>An even shorter version of the code uses the <code>@eval</code> macro.</p>
<pre><code class="language-julia-repl">julia&gt; for op &#61; &#40;:sin, :cos, :tan, :log, :exp&#41;
    @eval Base.&#36;op&#40;a::MyNumber&#41; &#61; MyNumber&#40;&#36;op&#40;a.x&#41;&#41;
end</code></pre>
<p>For longer blocks of generated code, the <code>@eval</code> macro can proceed a code <code>block</code>:</p>
<pre><code class="language-julia-repl">julia&gt; @eval begin
    # multiple lines
end</code></pre>
</div>mimetext/htmlrootassigneelast_run_timestampA}Qm.persist_js_state·has_pluto_hook_features§cell_id$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01depends_on_disabled_cells§runtime &6published_object_keysdepends_on_skipped_cells§errored$bc66ff75-77ce-4487-ab2e-72800331839bqueued¤logsrunning¦outputbody<div class="markdown"><h1 id="The-:-Operator">The <code>:</code> Operator</h1>
<p>The <code>:</code> character has two syntatic purposes in Julia. It defines a <code>Symbol</code> or a <code>Quote</code>.</p>
<h2 id="Symbols">Symbols</h2>
<p>A <code>Symbol</code> is an interned string used as a building-block of an expression.</p>
<pre><code class="language-julia-repl">julia&gt; sym &#61; :foo
:foo

julia&gt; typeof&#40;sym&#41;
Symbol

julia&gt; sym &#61;&#61; Symbol&#40;&quot;foo&quot;&#41;
true</code></pre>
<p>The <code>Symbol</code> constructor takes a variable number of arguments and concatenates them together to create a <code>Symbol</code> string.</p>
<pre><code class="language-julia-repl">julia&gt; Symbol&#40;&quot;func&quot;, 10&#41;
:func10</code></pre>
<p>In the context of expressions, symbols are used to indicate access to variables. When an expression is evaluated, a symbol is replaced with the value bound to that symbol in the appropriate scope.</p>
<h2 id="Quoting">Quoting</h2>
<p>The second purpose of the <code>:</code> character is to create expression objects without using the explicit <code>Expr</code> constructor. This is referred to as <em>quoting</em>.</p>
<pre><code class="language-julia-repl">julia&gt; ex3 &#61; :&#40;3 * 4 &#43; 5&#41;
:&#40;3 * 4 &#43; 5&#41;

julia&gt; dump&#40;ex3&#41;
Expr
  head: Symbol call
  args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
    1: Symbol &#43;
    2: Expr
      head: Symbol call
      args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5

julia&gt; ex1 &#61;&#61; ex2 &#61;&#61; ex3
true</code></pre>
<p>So, there are three ways to construct an expression allowing the programmer to use whichever one is most convenient.</p>
<p>There is a second syntatic form of quoting, called a <code>quote</code> block &#40;i.e. <code>quote ... end</code>&#41;, that is commonly used for multiple expressions. For example:</p>
<pre><code class="language-julia-repl">julia&gt; ex4 &#61; quote
    x &#61; 1
    y &#61; 2
    x &#43; y
end
quote
    #&#61; REPL&#91;78&#93;:2 &#61;#
    x &#61; 1
    #&#61; REPL&#91;78&#93;:3 &#61;#
    y &#61; 2
    #&#61; REPL&#91;78&#93;:4 &#61;#
    x &#43; y
end

julia&gt; typeof&#40;ex4&#41;
Expr</code></pre>
<h2 id="Interpolation">Interpolation</h2>
<p>Julia allows <strong>interpolation</strong> of literals or expressions into quoted expressions by prefixing a variable with the <code>&#36;</code> character. For example:</p>
<pre><code class="language-julia-repl">julia&gt; a &#61; 1;
julia&gt; ex5 &#61; :&#40;&#36;a &#43; b&#41;
:&#40;1 &#43; b&#41;
julia&gt; dump&#40;ex5&#41;
Expr
  head: Symbol call
  args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
    1: Symbol &#43;
    2: Int64 1
    3: Symbol b</code></pre>
<p>Splatting is also possible.</p>
<pre><code class="language-julia-repl">julia&gt; args &#61; &#91;:x, :y, :x&#93;;
julia&gt; dump&#40;:&#40;f&#40;1, &#36;&#40;args...&#41;&#41;&#41;&#41;
Expr
  head: Symbol call
  args: Array&#123;Any&#125;&#40;&#40;5,&#41;&#41;
    1: Symbol f
    2: Int64 1
    3: Symbol x
    4: Symbol y
    5: Symbol x</code></pre>
<h2 id="Expression-evaluation">Expression evaluation</h2>
<p>Julia will evalution an expression in the global scope using <code>eval</code>.</p>
<pre><code class="language-julia-repl">julia&gt; eval&#40;ex1&#41;
17</code></pre>
<div class="admonition note"><p class="admonition-title">Note</p><p>Unlike Python, the use of <code>eval</code> in Julia is strongly discouraged.</p>
</div>
</div>mimetext/htmlrootassigneelast_run_timestampA}QmŰpersist_js_state·has_pluto_hook_features§cell_id$bc66ff75-77ce-4487-ab2e-72800331839bdepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$8eca8d1b-9077-4f56-a9ef-b901ff5844a9queued¤logsrunning¦outputbody<div class="markdown"><h1 id="Summary">Summary</h1>
<div class="admonition note"><p class="admonition-title"></p><ul>
<li><p>Macros simplify program development.</p>
</li>
<li></li>
</ul>
</div>
</div>mimetext/htmlrootassigneelast_run_timestampA}Qm_persist_js_state·has_pluto_hook_features§cell_id$8eca8d1b-9077-4f56-a9ef-b901ff5844a9depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$23fcb211-8b7e-404e-9847-cc57f5aa2cd6queued¤logsrunning¦outputbody<div class="markdown"><h1 id="Problems">Problems</h1>
<div class="admonition tip"><p class="admonition-title">Remember that you can get help either through `?` in a REPL or with "Live Docs" right here in Pluto (lower right-hand corner)</p></div>
</div>mimetext/htmlrootassigneelast_run_timestampA}Qm1persist_js_state·has_pluto_hook_features§cell_id$23fcb211-8b7e-404e-9847-cc57f5aa2cd6depends_on_disabled_cells§runtime 
published_object_keysdepends_on_skipped_cells§errored$39182b4b-a7a8-4a37-b543-121f744d5d65queued¤logsrunning¦outputbodyM<script>
	
// Load the library for consistent smooth scrolling
const {default: scrollIntoView} = await import("data:text/javascript;base64,dmFyIFE9ZT0+Im9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT1lJiYxPT09ZS5ub2RlVHlwZSxVPShlLHQpPT4oIXR8fCJoaWRkZW4iIT09ZSkmJiJ2aXNpYmxlIiE9PWUmJiJjbGlwIiE9PWUsQT0oZSx0KT0+e2lmKGUuY2xpZW50SGVpZ2h0PGUuc2Nyb2xsSGVpZ2h0fHxlLmNsaWVudFdpZHRoPGUuc2Nyb2xsV2lkdGgpe2xldCBsPWdldENvbXB1dGVkU3R5bGUoZSxudWxsKTtyZXR1cm4gVShsLm92ZXJmbG93WSx0KXx8VShsLm92ZXJmbG93WCx0KXx8KGU9PntsZXQgdD0oZT0+e2lmKCFlLm93bmVyRG9jdW1lbnR8fCFlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcpcmV0dXJuIG51bGw7dHJ5e3JldHVybiBlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcuZnJhbWVFbGVtZW50fWNhdGNoe3JldHVybiBudWxsfX0pKGUpO3JldHVybiEhdCYmKHQuY2xpZW50SGVpZ2h0PGUuc2Nyb2xsSGVpZ2h0fHx0LmNsaWVudFdpZHRoPGUuc2Nyb2xsV2lkdGgpfSkoZSl9cmV0dXJuITF9LFg9KGUsdCxsLG8sbixyLGkscyk9PnI8ZSYmaT50fHxyPmUmJmk8dD8wOnI8PWUmJnM8PWx8fGk+PXQmJnM+PWw/ci1lLW86aT50JiZzPGx8fHI8ZSYmcz5sP2ktdCtuOjAsJD1lPT5lLnBhcmVudEVsZW1lbnQ/PyhlLmdldFJvb3ROb2RlKCkuaG9zdHx8bnVsbCksdHQ9KGUsdCk9Pnt2YXIgbCxvLG4scjtpZih0eXBlb2YgZG9jdW1lbnQ+InUiKXJldHVybltdO2xldHtzY3JvbGxNb2RlOmksYmxvY2s6cyxpbmxpbmU6YSxib3VuZGFyeTpoLHNraXBPdmVyZmxvd0hpZGRlbkVsZW1lbnRzOnV9PXQsZz0iZnVuY3Rpb24iPT10eXBlb2YgaD9oOmU9PmUhPT1oO2lmKCFRKGUpKXRocm93IFR5cGVFcnJvcigiSW52YWxpZCB0YXJnZXQiKTtsZXQgdj1kb2N1bWVudC5zY3JvbGxpbmdFbGVtZW50fHxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsbT1bXSx3PWU7Zm9yKDtRKHcpJiZnKHcpOyl7aWYoKHc9JCh3KSk9PT12KXttLnB1c2godyk7YnJlYWt9bnVsbCE9dyYmdz09PWRvY3VtZW50LmJvZHkmJkEodykmJiFBKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCl8fG51bGwhPXcmJkEodyx1KSYmbS5wdXNoKHcpfWxldCBXPW51bGwhPShvPW51bGw9PShsPXdpbmRvdy52aXN1YWxWaWV3cG9ydCk/dm9pZCAwOmwud2lkdGgpP286aW5uZXJXaWR0aCxIPW51bGwhPShyPW51bGw9PShuPXdpbmRvdy52aXN1YWxWaWV3cG9ydCk/dm9pZCAwOm4uaGVpZ2h0KT9yOmlubmVySGVpZ2h0LHtzY3JvbGxYOl8sc2Nyb2xsWTp4fT13aW5kb3cse2hlaWdodDpFLHdpZHRoOlQsdG9wOk4scmlnaHQ6TCxib3R0b206WSxsZWZ0OkN9PWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksUj0ic3RhcnQiPT09c3x8Im5lYXJlc3QiPT09cz9OOiJlbmQiPT09cz9ZOk4rRS8yLFY9ImNlbnRlciI9PT1hP0MrVC8yOiJlbmQiPT09YT9MOkMsQj1bXTtmb3IobGV0IEQ9MDtEPG0ubGVuZ3RoO0QrKyl7bGV0IE89bVtEXSx7aGVpZ2h0Omosd2lkdGg6SSx0b3A6UyxyaWdodDpxLGJvdHRvbTp6LGxlZnQ6Rn09Ty5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtpZigiaWYtbmVlZGVkIj09PWkmJk4+PTAmJkM+PTAmJlk8PUgmJkw8PVcmJk4+PVMmJlk8PXomJkM+PUYmJkw8PXEpYnJlYWs7bGV0IEc9Z2V0Q29tcHV0ZWRTdHlsZShPKSxKPXBhcnNlSW50KEcuYm9yZGVyTGVmdFdpZHRoLDEwKSxLPXBhcnNlSW50KEcuYm9yZGVyVG9wV2lkdGgsMTApLFA9cGFyc2VJbnQoRy5ib3JkZXJSaWdodFdpZHRoLDEwKSxaPXBhcnNlSW50KEcuYm9yZGVyQm90dG9tV2lkdGgsMTApLGVlPTAsZXQ9MCxlbD0ib2Zmc2V0V2lkdGgiaW4gTz9PLm9mZnNldFdpZHRoLU8uY2xpZW50V2lkdGgtSi1QOjAsZW89Im9mZnNldEhlaWdodCJpbiBPP08ub2Zmc2V0SGVpZ2h0LU8uY2xpZW50SGVpZ2h0LUstWjowLGVuPSJvZmZzZXRXaWR0aCJpbiBPPzA9PT1PLm9mZnNldFdpZHRoPzA6SS9PLm9mZnNldFdpZHRoOjAsZXI9Im9mZnNldEhlaWdodCJpbiBPPzA9PT1PLm9mZnNldEhlaWdodD8wOmovTy5vZmZzZXRIZWlnaHQ6MDtpZih2PT09TyllZT0ic3RhcnQiPT09cz9SOiJlbmQiPT09cz9SLUg6Im5lYXJlc3QiPT09cz9YKHgseCtILEgsSyxaLHgrUix4K1IrRSxFKTpSLUgvMixldD0ic3RhcnQiPT09YT9WOiJjZW50ZXIiPT09YT9WLVcvMjoiZW5kIj09PWE/Vi1XOlgoXyxfK1csVyxKLFAsXytWLF8rVitULFQpLGVlPU1hdGgubWF4KDAsZWUreCksZXQ9TWF0aC5tYXgoMCxldCtfKTtlbHNle2VlPSJzdGFydCI9PT1zP1ItUy1LOiJlbmQiPT09cz9SLXorWitlbzoibmVhcmVzdCI9PT1zP1goUyx6LGosSyxaK2VvLFIsUitFLEUpOlItKFMrai8yKStlby8yLGV0PSJzdGFydCI9PT1hP1YtRi1KOiJjZW50ZXIiPT09YT9WLShGK0kvMikrZWwvMjoiZW5kIj09PWE/Vi1xK1ArZWw6WChGLHEsSSxKLFArZWwsVixWK1QsVCk7bGV0e3Njcm9sbExlZnQ6ZWksc2Nyb2xsVG9wOmVkfT1PO2VlPU1hdGgubWF4KDAsTWF0aC5taW4oZWQrZWUvZXIsTy5zY3JvbGxIZWlnaHQtai9lcitlbykpLGV0PU1hdGgubWF4KDAsTWF0aC5taW4oZWkrZXQvZW4sTy5zY3JvbGxXaWR0aC1JL2VuK2VsKSksUis9ZWQtZWUsVis9ZWktZXR9Qi5wdXNoKHtlbDpPLHRvcDplZSxsZWZ0OmV0fSl9cmV0dXJuIEJ9LGY9ZT0+e3ZhciB0O3JldHVybiExPT09ZT97YmxvY2s6ImVuZCIsaW5saW5lOiJuZWFyZXN0In06KHQ9ZSk9PT1PYmplY3QodCkmJjAhPT1PYmplY3Qua2V5cyh0KS5sZW5ndGg/ZTp7YmxvY2s6InN0YXJ0IixpbmxpbmU6Im5lYXJlc3QifX07ZnVuY3Rpb24gYyhlLHQpe3ZhciBsO2lmKCFlLmlzQ29ubmVjdGVkfHwhKGU9PntsZXQgdD1lO2Zvcig7dCYmdC5wYXJlbnROb2RlOyl7aWYodC5wYXJlbnROb2RlPT09ZG9jdW1lbnQpcmV0dXJuITA7dD10LnBhcmVudE5vZGUgaW5zdGFuY2VvZiBTaGFkb3dSb290P3QucGFyZW50Tm9kZS5ob3N0OnQucGFyZW50Tm9kZX1yZXR1cm4hMX0pKGUpKXJldHVybjtpZigib2JqZWN0Ij09dHlwZW9mKGw9dCkmJiJmdW5jdGlvbiI9PXR5cGVvZiBsLmJlaGF2aW9yKXJldHVybiB0LmJlaGF2aW9yKHR0KGUsdCkpO2xldCBvPSJib29sZWFuIj09dHlwZW9mIHR8fG51bGw9PXQ/dm9pZCAwOnQuYmVoYXZpb3I7Zm9yKGxldHtlbDpuLHRvcDpyLGxlZnQ6aX1vZiB0dChlLGYodCkpKW4uc2Nyb2xsKHt0b3A6cixsZWZ0OmksYmVoYXZpb3I6b30pfXZhciBkLHA9KCk9PihkfHwoZD0icGVyZm9ybWFuY2UiaW4gd2luZG93P3BlcmZvcm1hbmNlLm5vdy5iaW5kKHBlcmZvcm1hbmNlKTpEYXRlLm5vdyksZCgpKTtmdW5jdGlvbiBiKGUpe2xldCB0PU1hdGgubWluKChwKCktZS5zdGFydFRpbWUpL2UuZHVyYXRpb24sMSksbD1lLmVhc2UodCksbz1lLnN0YXJ0WCsoZS54LWUuc3RhcnRYKSpsLG49ZS5zdGFydFkrKGUueS1lLnN0YXJ0WSkqbDtlLm1ldGhvZChvLG4sdCxsKSxvIT09ZS54fHxuIT09ZS55P3JlcXVlc3RBbmltYXRpb25GcmFtZSgoKT0+YihlKSk6ZS5jYigpfWZ1bmN0aW9uIHkoZSx0LGwpe2xldCBvPWFyZ3VtZW50cy5sZW5ndGg+MyYmdm9pZCAwIT09YXJndW1lbnRzWzNdP2FyZ3VtZW50c1szXTo2MDAsbj1hcmd1bWVudHMubGVuZ3RoPjQmJnZvaWQgMCE9PWFyZ3VtZW50c1s0XT9hcmd1bWVudHNbNF06ZT0+MSstLWUqZSplKmUqZSxyPWFyZ3VtZW50cy5sZW5ndGg+NT9hcmd1bWVudHNbNV06dm9pZCAwLGk9YXJndW1lbnRzLmxlbmd0aD42P2FyZ3VtZW50c1s2XTp2b2lkIDAscz1lLnNjcm9sbExlZnQsYT1lLnNjcm9sbFRvcDtiKHtzY3JvbGxhYmxlOmUsbWV0aG9kKHQsbCxvLG4pe2xldCByPU1hdGguY2VpbCh0KSxzPU1hdGguY2VpbChsKTtlLnNjcm9sbExlZnQ9cixlLnNjcm9sbFRvcD1zLGk/Lih7dGFyZ2V0OmUsZWxhcHNlZDpvLHZhbHVlOm4sbGVmdDpyLHRvcDpzfSl9LHN0YXJ0VGltZTpwKCksc3RhcnRYOnMsc3RhcnRZOmEseDp0LHk6bCxkdXJhdGlvbjpvLGVhc2U6bixjYjpyfSl9dmFyIE09ZT0+ZSYmIWUuYmVoYXZpb3J8fCJzbW9vdGgiPT09ZS5iZWhhdmlvcixrPWZ1bmN0aW9uKGUsdCl7bGV0IGw9dHx8e307cmV0dXJuIE0obCk/YyhlLHtibG9jazpsLmJsb2NrLGlubGluZTpsLmlubGluZSxzY3JvbGxNb2RlOmwuc2Nyb2xsTW9kZSxib3VuZGFyeTpsLmJvdW5kYXJ5LHNraXBPdmVyZmxvd0hpZGRlbkVsZW1lbnRzOmwuc2tpcE92ZXJmbG93SGlkZGVuRWxlbWVudHMsYmVoYXZpb3I6ZT0+UHJvbWlzZS5hbGwoZS5yZWR1Y2UoKGUsdCk9PntsZXR7ZWw6byxsZWZ0Om4sdG9wOnJ9PXQsaT1vLnNjcm9sbExlZnQscz1vLnNjcm9sbFRvcDtyZXR1cm4gaT09PW4mJnM9PT1yP2U6Wy4uLmUsbmV3IFByb21pc2UoZT0+eShvLG4scixsLmR1cmF0aW9uLGwuZWFzZSwoKT0+ZSh7ZWw6byxsZWZ0OltpLG5dLHRvcDpbcyxyXX0pLGwub25TY3JvbGxDaGFuZ2UpKV19LFtdKSl9KTpQcm9taXNlLnJlc29sdmUoYyhlLHQpKX07ZXhwb3J0e2sgYXMgZGVmYXVsdH07")

const indent = true
const aside = true
const title_text = "2-2: Using Macros"
const include_definitions = false


const tocNode = html`<nav class="plutoui-toc">
	<header>
	 <span class="toc-toggle open-toc"></span>
	 <span class="toc-toggle closed-toc"></span>
	 ${title_text}
	</header>
	<section></section>
</nav>`

tocNode.classList.toggle("aside", aside)
tocNode.classList.toggle("indent", indent)


const getParentCell = el => el.closest("pluto-cell")

const getHeaders = () => {
	const depth = Math.max(1, Math.min(6, 4)) // should be in range 1:6
	const range = Array.from({length: depth}, (x, i) => i+1) // [1, ..., depth]
	
	const selector = [
		...(include_definitions ? [
			`pluto-notebook pluto-cell .pluto-docs-binding`, 
			`pluto-notebook pluto-cell assignee:not(:empty)`, 
		] : []),
		...range.map(i => `pluto-notebook pluto-cell h${i}`)
	].join(",")
	return Array.from(document.querySelectorAll(selector)).filter(el => 
		// exclude headers inside of a pluto-docs-binding block
		!(el.nodeName.startsWith("H") && el.closest(".pluto-docs-binding"))
	)
}


const document_click_handler = (event) => {
	const path = (event.path || event.composedPath())
	const toc = path.find(elem => elem?.classList?.contains?.("toc-toggle"))
	if (toc) {
		event.stopImmediatePropagation()
		toc.closest(".plutoui-toc").classList.toggle("hide")
	}
}

document.addEventListener("click", document_click_handler)


const header_to_index_entry_map = new Map()
const currently_highlighted_set = new Set()

const last_toc_element_click_time = { current: 0 }

const intersection_callback = (ixs) => {
	let on_top = ixs.filter(ix => ix.intersectionRatio > 0 && ix.intersectionRect.y < ix.rootBounds.height / 2)
	if(on_top.length > 0){
		currently_highlighted_set.forEach(a => a.classList.remove("in-view"))
		currently_highlighted_set.clear()
		on_top.slice(0,1).forEach(i => {
			let div = header_to_index_entry_map.get(i.target)
			div.classList.add("in-view")
			currently_highlighted_set.add(div)
			
			/// scroll into view
			/*
			const toc_height = tocNode.offsetHeight
			const div_pos = div.offsetTop
			const div_height = div.offsetHeight
			const current_scroll = tocNode.scrollTop
			const header_height = tocNode.querySelector("header").offsetHeight
			
			const scroll_to_top = div_pos - header_height
			const scroll_to_bottom = div_pos + div_height - toc_height
			
			// if we set a scrollTop, then the browser will stop any currently ongoing smoothscroll animation. So let's only do this if you are not currently in a smoothscroll.
			if(Date.now() - last_toc_element_click_time.current >= 2000)
				if(current_scroll < scroll_to_bottom){
					tocNode.scrollTop = scroll_to_bottom
				} else if(current_scroll > scroll_to_top){
					tocNode.scrollTop = scroll_to_top
				}
			*/
		})
	}
}
let intersection_observer_1 = new IntersectionObserver(intersection_callback, {
	root: null, // i.e. the viewport
  	threshold: 1,
	rootMargin: "-15px", // slightly smaller than the viewport
	// delay: 100,
})
let intersection_observer_2 = new IntersectionObserver(intersection_callback, {
	root: null, // i.e. the viewport
  	threshold: 1,
	rootMargin: "15px", // slightly larger than the viewport
	// delay: 100,
})

const render = (elements) => {
	header_to_index_entry_map.clear()
	currently_highlighted_set.clear()
	intersection_observer_1.disconnect()
	intersection_observer_2.disconnect()

		let last_level = `H1`
	return html`${elements.map(h => {
	const parent_cell = getParentCell(h)

		let [className, title_el] = h.matches(`.pluto-docs-binding`) ? ["pluto-docs-binding-el", h.firstElementChild] : [h.nodeName, h]

	const a = html`<a 
		class="${className}" 
		title="${title_el.innerText}"
		href="#${parent_cell.id}"
	>${title_el.innerHTML}</a>`
	/* a.onmouseover=()=>{
		parent_cell.firstElementChild.classList.add(
			'highlight-pluto-cell-shoulder'
		)
	}
	a.onmouseout=() => {
		parent_cell.firstElementChild.classList.remove(
			'highlight-pluto-cell-shoulder'
		)
	} */
		
		
	a.onclick=(e) => {
		e.preventDefault();
		last_toc_element_click_time.current = Date.now()
		scrollIntoView(h, {
			behavior: 'smooth', 
			block: 'start',
		}).then(() => 
			// sometimes it doesn't scroll to the right place
			// solution: try a second time!
			scrollIntoView(h, {
				behavior: 'smooth', 
				block: 'start',
			})
	   )
	}

	const row =  html`<div class="toc-row ${className} after-${last_level}">${a}</div>`
		intersection_observer_1.observe(title_el)
		intersection_observer_2.observe(title_el)
		header_to_index_entry_map.set(title_el, row)

	if(className.startsWith("H"))
		last_level = className
		
	return row
})}`
}

const invalidated = { current: false }

const updateCallback = () => {
	if (!invalidated.current) {
		tocNode.querySelector("section").replaceWith(
			html`<section>${render(getHeaders())}</section>`
		)
	}
}
updateCallback()
setTimeout(updateCallback, 100)
setTimeout(updateCallback, 1000)
setTimeout(updateCallback, 5000)

const notebook = document.querySelector("pluto-notebook")


// We have a mutationobserver for each cell:
const mut_observers = {
	current: [],
}

const createCellObservers = () => {
	mut_observers.current.forEach((o) => o.disconnect())
	mut_observers.current = Array.from(notebook.querySelectorAll("pluto-cell")).map(el => {
		const o = new MutationObserver(updateCallback)
		o.observe(el, {attributeFilter: ["class"]})
		return o
	})
}
createCellObservers()

// And one for the notebook's child list, which updates our cell observers:
const notebookObserver = new MutationObserver(() => {
	updateCallback()
	createCellObservers()
})
notebookObserver.observe(notebook, {childList: true})

// And finally, an observer for the document.body classList, to make sure that the toc also works when it is loaded during notebook initialization
const bodyClassObserver = new MutationObserver(updateCallback)
bodyClassObserver.observe(document.body, {attributeFilter: ["class"]})

// Hide/show the ToC when the screen gets small
let match_listener = () => 
	tocNode.classList.toggle("hide", (tocNode.closest("pluto-editor") ?? document.body).scrollWidth < 1000)
for(let s of [1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000]) {
	let m = matchMedia(`(max-width: ${s}px)`)
	m.addListener(match_listener)
	invalidation.then(() => m.removeListener(match_listener))
}
match_listener()

invalidation.then(() => {
	invalidated.current = true
	intersection_observer_1.disconnect()
	intersection_observer_2.disconnect()
	notebookObserver.disconnect()
	bodyClassObserver.disconnect()
	mut_observers.current.forEach((o) => o.disconnect())
	document.removeEventListener("click", document_click_handler)
})

return tocNode
</script>
<style>
@media not print {

.plutoui-toc {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Cantarell, "Apple Color Emoji",
		"Segoe UI Emoji", "Segoe UI Symbol", system-ui, sans-serif;
	--main-bg-color: #fafafa;
	--pluto-output-color: hsl(0, 0%, 36%);
	--pluto-output-h-color: hsl(0, 0%, 21%);
	--sidebar-li-active-bg: rgb(235, 235, 235);
	--icon-filter: unset;
}

@media (prefers-color-scheme: dark) {
	.plutoui-toc {
		--main-bg-color: #303030;
		--pluto-output-color: hsl(0, 0%, 90%);
		--pluto-output-h-color: hsl(0, 0%, 97%);
		--sidebar-li-active-bg: rgb(82, 82, 82);
		--icon-filter: invert(1);
	}
}

.plutoui-toc.aside {
	color: var(--pluto-output-color);
	position: fixed;
	right: 1rem;
	top: 5rem;
	width: min(80vw, 300px);
	padding: 0.5rem;
	padding-top: 0em;
	/* border: 3px solid rgba(0, 0, 0, 0.15); */
	border-radius: 10px;
	/* box-shadow: 0 0 11px 0px #00000010; */
	max-height: calc(100vh - 5rem - 90px);
	overflow: auto;
	z-index: 40;
	background-color: var(--main-bg-color);
	transition: transform 300ms cubic-bezier(0.18, 0.89, 0.45, 1.12);
}

.plutoui-toc.aside.hide {
	transform: translateX(calc(100% - 28px));
}
.plutoui-toc.aside.hide section {
	display: none;
}
.plutoui-toc.aside.hide header {
	margin-bottom: 0em;
	padding-bottom: 0em;
	border-bottom: none;
}
}  /* End of Media print query */
.plutoui-toc.aside.hide .open-toc,
.plutoui-toc.aside:not(.hide) .closed-toc,
.plutoui-toc:not(.aside) .closed-toc {
	display: none;
}

@media (prefers-reduced-motion) {
  .plutoui-toc.aside {
	transition-duration: 0s;
  }
}

.toc-toggle {
	cursor: pointer;
    padding: 1em;
    margin: -1em;
    margin-right: -0.7em;
    line-height: 1em;
    display: flex;
}

.toc-toggle::before {
    content: "";
    display: inline-block;
    height: 1em;
    width: 1em;
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/list-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LW88L3RpdGxlPjxsaW5lIHgxPSIxNjAiIHkxPSIxNDQiIHgyPSI0NDgiIHkyPSIxNDQiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozMnB4Ii8+PGxpbmUgeDE9IjE2MCIgeTE9IjI1NiIgeDI9IjQ0OCIgeTI9IjI1NiIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjMycHgiLz48bGluZSB4MT0iMTYwIiB5MT0iMzY4IiB4Mj0iNDQ4IiB5Mj0iMzY4IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MzJweCIvPjxjaXJjbGUgY3g9IjgwIiBjeT0iMTQ0IiByPSIxNiIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjMycHgiLz48Y2lyY2xlIGN4PSI4MCIgY3k9IjI1NiIgcj0iMTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozMnB4Ii8+PGNpcmNsZSBjeD0iODAiIGN5PSIzNjgiIHI9IjE2IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MzJweCIvPjwvc3ZnPg==");
    background-size: 1em;
	filter: var(--icon-filter);
}

.aside .toc-toggle.open-toc:hover::before {
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/arrow-forward-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LWE8L3RpdGxlPjxwb2x5bGluZSBwb2ludHM9IjI2OCAxMTIgNDEyIDI1NiAyNjggNDAwIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NDhweCIvPjxsaW5lIHgxPSIzOTIiIHkxPSIyNTYiIHgyPSIxMDAiIHkyPSIyNTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDo0OHB4Ii8+PC9zdmc+");
}
.aside .toc-toggle.closed-toc:hover::before {
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/arrow-back-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LWE8L3RpdGxlPjxwb2x5bGluZSBwb2ludHM9IjI0NCA0MDAgMTAwIDI1NiAyNDQgMTEyIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NDhweCIvPjxsaW5lIHgxPSIxMjAiIHkxPSIyNTYiIHgyPSI0MTIiIHkyPSIyNTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDo0OHB4Ii8+PC9zdmc+");
}



.plutoui-toc header {
	display: flex;
	align-items: center;
	gap: .3em;
	font-size: 1.5em;
	/* margin-top: -0.1em; */
	margin-bottom: 0.4em;
	padding: 0.5rem;
	margin-left: 0;
	margin-right: 0;
	font-weight: bold;
	/* border-bottom: 2px solid rgba(0, 0, 0, 0.15); */
	position: sticky;
	top: 0px;
	background: var(--main-bg-color);
	z-index: 41;
}
.plutoui-toc.aside header {
	padding-left: 0;
	padding-right: 0;
}

.plutoui-toc section .toc-row {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	padding: .1em;
	border-radius: .2em;
}

.plutoui-toc section .toc-row.H1 {
	margin-top: 1em;
}


.plutoui-toc.aside section .toc-row.in-view {
	background: var(--sidebar-li-active-bg);
}


	
.highlight-pluto-cell-shoulder {
	background: rgba(0, 0, 0, 0.05);
	background-clip: padding-box;
}

.plutoui-toc section a {
	text-decoration: none;
	font-weight: normal;
	color: var(--pluto-output-color);
}
.plutoui-toc section a:hover {
	color: var(--pluto-output-h-color);
}

.plutoui-toc.indent section a.H1 {
	font-weight: 700;
	line-height: 1em;
}

.plutoui-toc.indent section .after-H2 a { padding-left: 10px; }
.plutoui-toc.indent section .after-H3 a { padding-left: 20px; }
.plutoui-toc.indent section .after-H4 a { padding-left: 30px; }
.plutoui-toc.indent section .after-H5 a { padding-left: 40px; }
.plutoui-toc.indent section .after-H6 a { padding-left: 50px; }

.plutoui-toc.indent section a.H1 { padding-left: 0px; }
.plutoui-toc.indent section a.H2 { padding-left: 10px; }
.plutoui-toc.indent section a.H3 { padding-left: 20px; }
.plutoui-toc.indent section a.H4 { padding-left: 30px; }
.plutoui-toc.indent section a.H5 { padding-left: 40px; }
.plutoui-toc.indent section a.H6 { padding-left: 50px; }


.plutoui-toc.indent section a.pluto-docs-binding-el,
.plutoui-toc.indent section a.ASSIGNEE
	{
	font-family: JuliaMono, monospace;
	font-size: .8em;
	/* background: black; */
	font-weight: 700;
    font-style: italic;
	color: var(--cm-var-color); /* this is stealing a variable from Pluto, but it's fine if that doesnt work */
}
.plutoui-toc.indent section a.pluto-docs-binding-el::before,
.plutoui-toc.indent section a.ASSIGNEE::before
	{
	content: "> ";
	opacity: .3;
}
</style>
mimetext/htmlrootassigneelast_run_timestampA}Qy*persist_js_state·has_pluto_hook_features§cell_id$39182b4b-a7a8-4a37-b543-121f744d5d65depends_on_disabled_cells§runtimeIpublished_object_keysdepends_on_skipped_cells§errored$58b86c26-d8ba-404d-bc1e-9f8a21de2e38queued¤logsrunning¦outputbodyٌ<div class="markdown"><h2 id="1:">1:</h2>
<div class="admonition warning"><p class="admonition-title"></p><ul>
<li></li>
</ul>
</div>
</div>mimetext/htmlrootassigneelast_run_timestampA}QmRLpersist_js_state·has_pluto_hook_features§cell_id$58b86c26-d8ba-404d-bc1e-9f8a21de2e38depends_on_disabled_cells§runtime !mpublished_object_keysdepends_on_skipped_cells§errored$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8queued¤logsrunning¦outputbody<div class="markdown"><h1 id="Why-Macros">Why Macros</h1>
<p>Unlike other interactive languages, such as Matlab, Python, and R, Julia has macros. They are a very powerful programming construct. Macros modify existing source code or generate entirely new code. In essence, <strong>they simplify programming by automating mundane coding tasks.</strong></p>
<p>Preprocessor &quot;macro&quot; systems, like that of C/C&#43;&#43;, work at the source code level by perform textual manipulation and substitution before any parsing or interpretation is done. For example the following C/C&#43;&#43; macro expression tells the compiler to insert the code between the <code>#if</code> and <code>#endif</code> statements when <code>NAME</code> is defined.</p>
<pre><code>#if defined&#40;NAME&#41; ... #endif</code></pre>
<p>Whereas, Julia macros work at the level of the abstract syntax tree after parsing, but before compilation is done.</p>
</div>mimetext/htmlrootassigneelast_run_timestampA}Qm.#persist_js_state·has_pluto_hook_features§cell_id$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8depends_on_disabled_cells§runtime ^published_object_keysdepends_on_skipped_cells§errored$7c6e05a0-b0e4-4278-bb1a-e9316469d3cequeued¤logsrunning¦outputbody٢<div class="markdown"><div class="admonition note"><p class="admonition-title">2-2: Using Macros</p><p><strong>Last Updated: 2 May 2026</strong></p>
</div>
</div>mimetext/htmlrootassigneelast_run_timestampA}Qz_Ӱpersist_js_state·has_pluto_hook_features§cell_id$7c6e05a0-b0e4-4278-bb1a-e9316469d3cedepends_on_disabled_cells§runtime9published_object_keysdepends_on_skipped_cells§errored$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eaqueued¤logsrunning¦outputbody^<div class="markdown"><h1 id="The-Abstract-Syntax-Tree">The Abstract Syntax Tree</h1>
<p>Nearly all computer languages use an abstract syntax tree &#40;AST&#41; to parse the syntax of the language. In other words, the strings of characters that humans can read must be converted to a language that computers can read. The following snippet of Julia code represents how that is performed. The first line creates a string expression. The second line parses that expression, the third line prints the type of the parsed expression, namely an <code>Expr</code> type, and the fourth line prints the AST.</p>
<p>The <code>Meta.parse</code> statement in line 2 converts the mathematical expression in line 1 into an AST.</p>
<pre><code class="language-julia-repl">julia&gt; str1 &#61; &quot;3 * 4 &#43; 5&quot;
&quot;3 * 4 &#43; 5&quot;

julia&gt; ex1 &#61; Meta.parse&#40;str1&#41;
:&#40;3 * 4 &#43; 5&#41;

julia&gt; typeof&#40;ex1&#41;
Expr</code></pre>
<p>Let&#39;s dump or print the AST of the above expression.</p>
<pre><code class="language-julia-repl">julia&gt; dump&#40;ex1&#41;
Expr
  head: Symbol call
  args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
    1: Symbol &#43;
    2: Expr
      head: Symbol call
      args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5</code></pre>
<p>The <code>Expr</code> type has two fields, a <code>head</code> and an <code>args</code>. The <code>head</code> declares the item is a function <code>call</code> of type <code>Symbol</code> and the <code>args</code> is an <code>Array</code> of function arguments, namely the <code>&#43;</code> operator of type <code>Symbol</code> and the two values to be added. The first value is another <code>Expr</code> type and the second is a 64-bit integer. The second nested <code>Expr</code> is also composed of a <code>Symbol</code> call. Its arguments are the multiplication <code>*</code> operation of type <code>Symbol</code> and two 64-bit integers. Note that the multiplication operation is nested in the addition operation, since multiplication has precedence over addition.</p>
<p>Note that the expression <code>ex1</code> can be written directly in AST syntax.</p>
<pre><code class="language-julia-repl">julia&gt; ex2 &#61; Expr&#40;:call, :&#43;, Expr&#40;:call, :*, 3, 4&#41;, 5&#41;
:&#40;3 * 4 &#43; 5&#41;

julia&gt; dump&#40;ex2&#41;
Expr
  head: Symbol call
  args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
    1: Symbol &#43;
    2: Expr
      head: Symbol call
      args: Array&#123;Any&#125;&#40;&#40;3,&#41;&#41;
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5
julia&gt; ex1 &#61;&#61; ex2
true</code></pre>
<div class="admonition note"><p class="admonition-title">Note</p><p>If you prefer writing code as an AST, you can do so in Julia.</p>
<p>However, you may not be popular with other coders.</p>
</div>
</div>mimetext/htmlrootassigneelast_run_timestampA}QmaVpersist_js_state·has_pluto_hook_features§cell_id$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eadepends_on_disabled_cells§runtime 
published_object_keysdepends_on_skipped_cells§errored±cell_dependencies$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01precedence_heuristic	cell_id$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01downstream_cells_mapupstream_cells_map@md_strgetindex$bc66ff75-77ce-4487-ab2e-72800331839bprecedence_heuristic	cell_id$bc66ff75-77ce-4487-ab2e-72800331839bdownstream_cells_mapupstream_cells_map@md_strgetindex$8eca8d1b-9077-4f56-a9ef-b901ff5844a9precedence_heuristic	cell_id$8eca8d1b-9077-4f56-a9ef-b901ff5844a9downstream_cells_mapupstream_cells_map@md_strgetindex$23fcb211-8b7e-404e-9847-cc57f5aa2cd6precedence_heuristic	cell_id$23fcb211-8b7e-404e-9847-cc57f5aa2cd6downstream_cells_mapupstream_cells_map@md_strgetindex$39182b4b-a7a8-4a37-b543-121f744d5d65precedence_heuristiccell_id$39182b4b-a7a8-4a37-b543-121f744d5d65downstream_cells_mapDates$7c6e05a0-b0e4-4278-bb1a-e9316469d3cePlutoUIHypertextLiteralupstream_cells_mapTableOfContents$58b86c26-d8ba-404d-bc1e-9f8a21de2e38precedence_heuristic	cell_id$58b86c26-d8ba-404d-bc1e-9f8a21de2e38downstream_cells_mapupstream_cells_map@md_strgetindex$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8precedence_heuristic	cell_id$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8downstream_cells_mapupstream_cells_map@md_strgetindex$7c6e05a0-b0e4-4278-bb1a-e9316469d3ceprecedence_heuristic	cell_id$7c6e05a0-b0e4-4278-bb1a-e9316469d3cedownstream_cells_mapupstream_cells_maptodayDates$39182b4b-a7a8-4a37-b543-121f744d5d65Dates.format|>@dateformat_strMarkdown$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eaprecedence_heuristic	cell_id$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eadownstream_cells_mapupstream_cells_map@md_strgetindexcell_execution_order$39182b4b-a7a8-4a37-b543-121f744d5d65$7c6e05a0-b0e4-4278-bb1a-e9316469d3ce$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8$2b1abe2e-fc7a-4d3a-9f65-b820eaff70ea$bc66ff75-77ce-4487-ab2e-72800331839b$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01$8eca8d1b-9077-4f56-a9ef-b901ff5844a9$23fcb211-8b7e-404e-9847-cc57f5aa2cd6$58b86c26-d8ba-404d-bc1e-9f8a21de2e38last_hot_reload_time        shortpath2-2: Using-Macros.jlprocess_statusreadypathB/home/runner/work/workshop/workshop/notebooks/2-2: Using-Macros.jlpluto_versionv0.20.24last_save_timeA}QmZ-cell_order$7c6e05a0-b0e4-4278-bb1a-e9316469d3ce$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8$2b1abe2e-fc7a-4d3a-9f65-b820eaff70ea$bc66ff75-77ce-4487-ab2e-72800331839b$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01$8eca8d1b-9077-4f56-a9ef-b901ff5844a9$23fcb211-8b7e-404e-9847-cc57f5aa2cd6$58b86c26-d8ba-404d-bc1e-9f8a21de2e38$39182b4b-a7a8-4a37-b543-121f744d5d65published_objectsnbpkginstall_time_ns4ܬinstantiatedòinstalled_versionsDatesstdlibPlutoUI0.7.60HypertextLiteral0.9.5terminal_outputsDatesS
[0m[1mWaiting for other notebooks to finish Pkg operations...[22m
[90m===[39m

[0m[1mResolving...[22m
[90m===[39m
[36m[1m     Project[22m[39m No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Project.toml`
[32m[1m    Updating[22m[39m `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Manifest.toml`
  [90m[14a3606d] [39m[93m↑ MozillaCACerts_jll v2025.5.20 ⇒ v2025.11.4[39m

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39mnbpkg_syncS
[0m[1mWaiting for other notebooks to finish Pkg operations...[22m
[90m===[39m

[0m[1mResolving...[22m
[90m===[39m
[36m[1m     Project[22m[39m No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Project.toml`
[32m[1m    Updating[22m[39m `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Manifest.toml`
  [90m[14a3606d] [39m[93m↑ MozillaCACerts_jll v2025.5.20 ⇒ v2025.11.4[39m

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39mPlutoUIS
[0m[1mWaiting for other notebooks to finish Pkg operations...[22m
[90m===[39m

[0m[1mResolving...[22m
[90m===[39m
[36m[1m     Project[22m[39m No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Project.toml`
[32m[1m    Updating[22m[39m `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Manifest.toml`
  [90m[14a3606d] [39m[93m↑ MozillaCACerts_jll v2025.5.20 ⇒ v2025.11.4[39m

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39mHypertextLiteralS
[0m[1mWaiting for other notebooks to finish Pkg operations...[22m
[90m===[39m

[0m[1mResolving...[22m
[90m===[39m
[36m[1m     Project[22m[39m No packages added to or removed from `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Project.toml`
[32m[1m    Updating[22m[39m `~/.julia/scratchspaces/c3e4b0f8-55cb-11ea-2926-15256bba5781/pkg_envs/env_qcqgynokrz/Manifest.toml`
  [90m[14a3606d] [39m[93m↑ MozillaCACerts_jll v2025.5.20 ⇒ v2025.11.4[39m

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39menabled÷restart_recommended_msgrestart_required_msgbusy_packageswaiting_for_permission,waiting_for_permission_but_probably_disabled«cell_inputs$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01cell_id$3be5ecc9-58cf-457a-a5d4-c9ff6114ba01codemd"""
# Using Macros

## Creation

Defining a macro is like defining a function. For example,

```julia-repl
julia> macro sayhello(name)
    return :( println("Hello", $name))
end
@sayhello (macro with 1 method)
```

Now invoke the `@sayhello` macro.

```julia-repl
julia> @sayhello("world")
Helloworld
```

Parentheses around the arguments are optional.

```julia-repl
julia> @sayhello "world"
Helloworld
```

!!! note
    When using the parenthesized form, there should be no space between the macro name and the parentheses. Otherwise the argument list will be interpreted as a single argument containing a Tuple.

## Usage

Macros can be used for many tasks such as performing operations on blocks of code, such as timing expressions (`@time`), threading `for` loops (`@threads`), and converting expressions to broadcast form (`@.`). Another use is to generate code. When a significant amount of repetitive boilerplate code is required, it is common to generate it programmatically to avoid redundancy.

Consider the following example.

```julia-repl
julia> struct MyNumber
    x::Float64
end
```

We want to add a various methods to it. This can be done programmatically using a `for` loop.

```julia-repl
julia> length(methods(sin))
14

julia> for op = (:sin, :tan, :log, :exp)
    eval(quote
        Base.$op(a::MyNumber) = MyNumber($op(a.x))
	end)
end

julia> length(methods(sin))
15
```

A slightly shorter version of the above code generator that use the `:` prefix is:

```julia-repl
julia> for op = (:sin, :cos, :tan, :log, :exp)
    eval(:(Base.$op(a::MyNumber) = MyNumber($op(a.x))))
end
```

An even shorter version of the code uses the `@eval` macro.

```julia-repl
julia> for op = (:sin, :cos, :tan, :log, :exp)
    @eval Base.$op(a::MyNumber) = MyNumber($op(a.x))
end
```

For longer blocks of generated code, the `@eval` macro can proceed a code `block`:

```julia-repl
julia> @eval begin
    # multiple lines
end
```
"""metadatashow_logsèdisabled®skip_as_script«code_folded$bc66ff75-77ce-4487-ab2e-72800331839bcell_id$bc66ff75-77ce-4487-ab2e-72800331839bcode	ymd"""
# The `:` Operator

The `:` character has two syntatic purposes in Julia. It defines a `Symbol` or a `Quote`.

## Symbols

A `Symbol` is an interned string used as a building-block of an expression.

```julia-repl
julia> sym = :foo
:foo

julia> typeof(sym)
Symbol

julia> sym == Symbol("foo")
true
```

The `Symbol` constructor takes a variable number of arguments and concatenates them together to create a `Symbol` string.

```julia-repl
julia> Symbol("func", 10)
:func10
```

In the context of expressions, symbols are used to indicate access to variables. When an expression is evaluated, a symbol is replaced with the value bound to that symbol in the appropriate scope.

## Quoting

The second purpose of the `:` character is to create expression objects without using the explicit `Expr` constructor. This is referred to as *quoting*.

```julia-repl
julia> ex3 = :(3 * 4 + 5)
:(3 * 4 + 5)

julia> dump(ex3)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5

julia> ex1 == ex2 == ex3
true
```

So, there are three ways to construct an expression allowing the programmer to use whichever one is most convenient.

There is a second syntatic form of quoting, called a `quote` block (i.e. `quote ... end`), that is commonly used for multiple expressions. For example:

```julia-repl
julia> ex4 = quote
    x = 1
    y = 2
    x + y
end
quote
    #= REPL[78]:2 =#
    x = 1
    #= REPL[78]:3 =#
    y = 2
    #= REPL[78]:4 =#
    x + y
end

julia> typeof(ex4)
Expr
```

## Interpolation

Julia allows **interpolation** of literals or expressions into quoted expressions by prefixing a variable with the `$` character. For example:

```julia-repl
julia> a = 1;
julia> ex5 = :($a + b)
:(1 + b)
julia> dump(ex5)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Int64 1
    3: Symbol b
```

Splatting is also possible.

```julia-repl
julia> args = [:x, :y, :x];
julia> dump(:(f(1, $(args...))))
Expr
  head: Symbol call
  args: Array{Any}((5,))
    1: Symbol f
    2: Int64 1
    3: Symbol x
    4: Symbol y
    5: Symbol x
```

## Expression evaluation

Julia will evalution an expression in the global scope using `eval`.

```julia-repl
julia> eval(ex1)
17
```

!!! note
	Unlike Python, the use of `eval` in Julia is strongly discouraged.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$8eca8d1b-9077-4f56-a9ef-b901ff5844a9cell_id$8eca8d1b-9077-4f56-a9ef-b901ff5844a9codeQmd"""
# Summary
!!! note ""
    * Macros simplify program development.
    * 
"""metadatashow_logsèdisabled®skip_as_script«code_folded$23fcb211-8b7e-404e-9847-cc57f5aa2cd6cell_id$23fcb211-8b7e-404e-9847-cc57f5aa2cd6codeٜmd"""
# Problems
!!! tip "Remember that you can get help either through `?` in a REPL or with "Live Docs" right here in Pluto (lower right-hand corner)"
"""metadatashow_logsèdisabled®skip_as_script«code_folded$39182b4b-a7a8-4a37-b543-121f744d5d65cell_id$39182b4b-a7a8-4a37-b543-121f744d5d65codejbegin
	using Dates, PlutoUI, HypertextLiteral
	TableOfContents(title = "2-2: Using Macros", depth = 4)
endmetadatashow_logsèdisabled®skip_as_script«code_folded$58b86c26-d8ba-404d-bc1e-9f8a21de2e38cell_id$58b86c26-d8ba-404d-bc1e-9f8a21de2e38code#md"""
## 1: 
!!! warning ""
	* 
"""metadatashow_logsèdisabled®skip_as_script«code_folded$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8cell_id$61ba1a79-3f3f-4d4f-a43e-e3d8883787e8codemd"""
# Why Macros

Unlike other interactive languages, such as Matlab, Python, and R, Julia has macros. They are a very powerful programming construct. Macros modify existing source code or generate entirely new code. In essence, **they simplify programming by automating mundane coding tasks.**

Preprocessor "macro" systems, like that of C/C++, work at the source code level by perform textual manipulation and substitution before any parsing or interpretation is done. For example the following C/C++ macro expression tells the compiler to insert the code between the `#if` and `#endif` statements when `NAME` is defined.

```
#if defined(NAME) ... #endif
```

Whereas, Julia macros work at the level of the abstract syntax tree after parsing, but before compilation is done.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$7c6e05a0-b0e4-4278-bb1a-e9316469d3cecell_id$7c6e05a0-b0e4-4278-bb1a-e9316469d3cecodex"""
!!! note "2-2: Using Macros"
    **Last Updated: $(Dates.format(today(), dateformat"d u Y"))**
""" |> Markdown.parsemetadatashow_logsèdisabled®skip_as_script«code_folded$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eacell_id$2b1abe2e-fc7a-4d3a-9f65-b820eaff70eacodemd"""
# The Abstract Syntax Tree

Nearly all computer languages use an abstract syntax tree (AST) to parse the syntax of the language. In other words, the strings of characters that humans can read must be converted to a language that computers can read. The following snippet of Julia code represents how that is performed. The first line creates a string expression. The second line parses that expression, the third line prints the type of the parsed expression, namely an `Expr` type, and the fourth line prints the AST.

The `Meta.parse` statement in line 2 converts the mathematical expression in line 1 into an AST.

```julia-repl
julia> str1 = "3 * 4 + 5"
"3 * 4 + 5"

julia> ex1 = Meta.parse(str1)
:(3 * 4 + 5)

julia> typeof(ex1)
Expr
```

Let's dump or print the AST of the above expression.

```julia-repl
julia> dump(ex1)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5
```

The `Expr` type has two fields, a `head` and an `args`. The `head` declares the item is a function `call` of type `Symbol` and the `args` is an `Array` of function arguments, namely the `+` operator of type `Symbol` and the two values to be added. The first value is another `Expr` type and the second is a 64-bit integer. The second nested `Expr` is also composed of a `Symbol` call. Its arguments are the multiplication `*` operation of type `Symbol` and two 64-bit integers. Note that the multiplication operation is nested in the addition operation, since multiplication has precedence over addition.

Note that the expression `ex1` can be written directly in AST syntax.

```julia-repl
julia> ex2 = Expr(:call, :+, Expr(:call, :*, 3, 4), 5)
:(3 * 4 + 5)

julia> dump(ex2)
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol +
    2: Expr
      head: Symbol call
      args: Array{Any}((3,))
        1: Symbol *
        2: Int64 3
        3: Int64 4
    3: Int64 5
julia> ex1 == ex2
true
```
!!! note
    If you prefer writing code as an AST, you can do so in Julia.

    However, you may not be popular with other coders.
"""metadatashow_logsèdisabled®skip_as_script«code_foldedënotebook_id$293544fc-45be-11f1-bae4-1944325c8a43in_temp_dir¨metadata